package edu.ucla.cs.rpc.multicast.network.message;

import java.io.Serializable;
import java.net.SocketAddress;

/**
 * An RPCMessage is an ObjectMessage that also contains a method name and an
 * array of arguments to the method call. The object (or Class, in the case of
 * static methods) is that which we invoke the method upon.
 * 
 * @author Chase Covello Philip Russell
 * 
 */
public class RPCMessage extends ObjectMessage {

	private static final long serialVersionUID = 6L;

	private final Serializable[] args;

	private final String methodName;

	/**
	 * Constructs a new RPCMessage with the given object (or Class), method
	 * name, arguments, and source address.
	 * 
	 * @param object
	 *            the object (or Class) to invoke the method upon.
	 * @param methodName
	 *            the method name.
	 * @param args
	 *            the method's arguments.
	 * @param source
	 *            the source of thi message.
	 */
	public RPCMessage(Serializable object, String methodName,
			Serializable[] args, SocketAddress source) {
		super(MessageType.RPC_MESSAGE, object, source);

		this.methodName = methodName;
		this.args = args;
	}

	/**
	 * Constructs a new RPCMessage using information from the given RPCMessage.
	 * 
	 * @param m
	 *            the message to copy.
	 */
	public RPCMessage(RPCMessage m) {
		super(m);

		this.methodName = m.methodName;
		this.args = m.args;
	}

	/**
	 * Returns the array of arguments to this method call.
	 * 
	 * @return the arguments.
	 */
	public Object[] getArgs() {
		return args;
	}

	/**
	 * Returns an array of Classes representing the type of the arguments to
	 * this method call.
	 * 
	 * @return the types of the arguments.
	 */
	public Class[] getArgTypes() {
		if (args == null)
			return null;

		Class[] types = new Class[args.length];
		for (int i = 0; i < args.length; i++)
			types[i] = args[i].getClass();

		return types;
	}

	/**
	 * Returns the method name.
	 * 
	 * @return the method name.
	 */
	public String getMethodName() {
		return methodName;
	}

	/**
	 * Returns a hash code for this RPCMessage. The hash code is given by the
	 * formula <code>super.hashCode() ^ methodName.hashCode()</code>.
	 */
	public int hashCode() {
		return super.hashCode() ^ methodName.hashCode();
	}

	/**
	 * Returns a string representation of this RPCMessage.
	 */
	public String toString() {
		return super.toString() + ", methodName=" + methodName;
	}
}
